/**
 * 
 */
package com.lorizz.picpub.web.controller.impl;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpSession;

import org.springframework.ui.Model;
import org.springframework.web.multipart.MultipartFile;

import com.lorizz.picpub.EntityListener;
import com.lorizz.picpub.query.UpmQueries;
import com.lorizz.picpub.services.EXIF;
import com.lorizz.picpub.services.ImageService;
import com.lorizz.picpub.services.ImageStore;
import com.lorizz.picpub.util.IdGenerator;
import com.lorizz.picpub.web.Constants;
import com.lorizz.picpub.web.WebException;
import com.lorizz.picpub.web.WebException.Code;
import com.lorizz.picpub.web.controller.UploadController;
import com.lorizz.upm.Album;
import com.lorizz.upm.Image;
import com.lorizz.upm.UserProfile;
import com.lorizz.upm.np.UserProfileNP;
import com.lorizz.upm.repository.Repository;

/**
 * @author wind hong
 * 
 */
public class UploadControllerImpl implements UploadController {

    private ImageStore imageStore;
    private ImageService imageService;
    private String tempDir;
    private Repository upmRepository;
    private List<EntityListener<Image>> imageListeners;
    private String storeCategory;

    public void setImageStore(ImageStore imageStore) {
        this.imageStore = imageStore;
    }

    public void setTempDir(String tempDir) {
        this.tempDir = tempDir;
        if (!this.tempDir.endsWith("/")) {
            this.tempDir += "/";
        }
    }
    public void setStoreCategory(String storeCategory) {
		this.storeCategory = storeCategory;
	}

	public void setUpmRepository(Repository upmRepository) {
        this.upmRepository = upmRepository;
    }

    public void setImageService(ImageService imageService) {
        this.imageService = imageService;
    }

    public void setImageListeners(List<EntityListener<Image>> imageListeners) {
		this.imageListeners = imageListeners;
	}

	@Override
    public String uploadSingle(MultipartFile imageFile, long albumId, HttpSession session, Model model) {
        UserProfileNP userProfileNP = (UserProfileNP) session.getAttribute(Constants.SESSION_USERPROFILE);
        String uuid = UUID.randomUUID().toString();
        File tempFolder = new File(tempDir + uuid);
        tempFolder.mkdirs();
        File tempFile = new File(tempFolder, imageFile.getOriginalFilename());
        try {
            imageFile.transferTo(tempFile);
        } catch (IllegalStateException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        Album album = null;
        if (albumId > 0) {
            album = upmRepository.loadAlbum(albumId);
            if (album != null && album.getUserProfile().getId() != userProfileNP.getId()) {
                throw new WebException(Code.ALBUM_NOT_UPLOADALBE);
            }
        }

        if (album == null) {
            String title = generateAlbumTitle();
            List<Album> existings = upmRepository.executeQuery(UpmQueries.instance().album(title, userProfileNP.getId()));
            if (existings.isEmpty()) {
                UserProfile userProfile = upmRepository.loadUserProfile(userProfileNP.getId());
                album = upmRepository.createAlbum();
                album.setTitle(generateAlbumTitle());
                album.setUserProfile(userProfile);
                upmRepository.persist(album);
            } else {
                album = existings.get(0);
            }
        }
        String uri = imageStore.store(storeCategory, tempFile);
        Image image = upmRepository.createImage();
        image.setFilename(tempFile.getName());
        image.setUri(uri);
        image.setUploaded(new Date());
        image.setSize(imageFile.getSize());
        image.setUuid(IdGenerator.generate());
        loadMetas(tempFile, image);
        upmRepository.persist(image);
        album.getImages().add(image);
        notifyListners(image);
        //return String.format("redirect:/i/v/%d/%d", album.getId(), image.getId());
        return image.getId().toString();
    }

    private void notifyListners(Image image) {
		for (EntityListener<Image> listener : imageListeners) {
			listener.notify(image, EntityListener.EntityAction.ADD);
		}
	}

	private String generateAlbumTitle() {
        return "public";
    }

    private void loadMetas(File tempFile, Image image) {
        Map<String, Object> metas = imageService.meta(tempFile);
        if (metas.containsKey(EXIF.DATETIME)) {
            Date taken = (Date) metas.get(EXIF.DATETIME);
            image.setTaken(taken);
            image.setModified(taken);
            metas.remove(taken);
        }
        if (!metas.isEmpty())
            image.getMeta().addAll(metas);
    }

    @Override
    public String upload(Model model, long albumId) {
    	model.addAttribute("albumId", albumId);
        return "upload";
    }

}
